#include "OSAL_TIMER.h"
#include "OSAL.h"
#include "stdlib.h"
#include "sys.h"
#include "misc.h"
/******************************************************************
 * @brief 通过链表实现定时器的功能
 * @step 创建定时器链表
 * 往定时器链表里面加入定时器
 * 轮询定时器链表查找有没超时的定时器
 * ****************************************************************/
static u32 OSAL_passTimeMS = 0;
static u32 OSAL_beforeTimeMS = 0;
static u32 OSAL_afterTimeMS = 0;
static Timer *timerList = NULL;
static uint8_t timerTaskID = 0;

/**
 * @fn OSAL_TimerInit
 * @brief 初始化OSAL的定时器功能
 * @param none
 * @return none
 */
void OSAL_TimerInit(uint8_t taskID)
{
    timerList = (Timer *)malloc(sizeof(Timer));
    timerList->nextTimer = NULL;
    OSAL_afterTimeMS = 0;
    OSAL_beforeTimeMS = 0;
    OSAL_passTimeMS = 0;
    OSAL_timerBaseInit(10);
    timerTaskID = taskID;
}
/**
 * @fn OSAL_TimerAdd
 * @brief 添加一个OSAL定时器
 * @param Timer-要添加的定时器
 * @return none
 */
void OSAL_TimerAdd(Timer *TimerEn)
{
    Timer *pTimer = NULL;
    Timer * pTimerEn = (Timer *)malloc(sizeof(Timer));
    pTimer = timerList;

    pTimerEn->nextTimer = pTimer->nextTimer;
    pTimer->nextTimer = pTimerEn;
    pTimerEn->taskEvent = TimerEn->taskEvent;
    pTimerEn->taskID = TimerEn->taskID;
 

}
/**
 * @fn OSAL_TimerDelete
 * @brief 删除一个OSAL定时器
 * @param Timer-要删除的定时器
 * @return none
 */
void OSAL_TimerDelete(Timer *TimerEn)
{

    Timer *pTimer = timerList->nextTimer;
    Timer *prevTimer = timerList;
    while (pTimer != NULL)
    {
        if (pTimer->taskID == TimerEn->taskID && pTimer->taskEvent == TimerEn->taskEvent)
        {
   
            prevTimer->nextTimer = pTimer->nextTimer;
            free(pTimer);
            break;
        }
        prevTimer = pTimer;
        pTimer = pTimer->nextTimer;
    }
}

/**
 * @fn OSAL_TimerRunning
 * @brief 运行定时器管理，计数定时器counter，到0设置相应事件
 * @param none
 * @return none
 */
void OSAL_TimerRunning(void)
{
    Timer *pTimer;
    OSAL_passTimeMS = OSAL_afterTimeMS - OSAL_beforeTimeMS;
    OSAL_beforeTimeMS = OSAL_afterTimeMS;
    if (OSAL_passTimeMS == 0)
        return;
    pTimer = timerList->nextTimer;
    while (pTimer != NULL)
    {

        if (pTimer->counter <= OSAL_passTimeMS)
        {
 
            OSAL_SetEvent(pTimer->taskID, pTimer->taskEvent);
            if(pTimer->periodic)
            {
                pTimer->counter = pTimer->period;
            }
            else
            {
                pTimer->counter = 0;
                OSAL_TimerDelete(pTimer);
            }
        
        }
        else
        {
            pTimer->counter = pTimer->counter - OSAL_passTimeMS;
        }
        pTimer = pTimer->nextTimer;
    }
}
/**
 * @fn OSAL_TimerOneShot
 * @brief 开启一个单次定时器
 * @param taskID-定时到后要设置事件的任务
 * @param taskEvent-要设置的事件
 * @param tickMS-定时时间，单位ms
 * @return none
 */
void OSAL_TimerOneShot(uint8_t taskID, uint16_t taskEvent, uint32_t tickMS)
{
    Timer timer;
    timer.counter = tickMS;
    timer.period = tickMS;
    timer.taskID = taskID;
    timer.taskEvent = taskEvent;
    timer.nextTimer = NULL;
    timer.periodic = false;
    OSAL_TimerAdd(&timer);
}



/**
 * @fn OSAL_TimerPeriodic
 * @brief 开启一个周期定时器
 * @param taskID-定时到后要设置事件的任务
 * @param taskEvent-要设置的事件
 * @param tickMS-定时时间，单位ms
 * @return none
 */
void OSAL_TimerPeriodic(uint8_t taskID, uint16_t taskEvent, uint32_t tickMS)
{
    Timer timer;
    timer.counter = tickMS;
    timer.period = tickMS;
    timer.taskID = taskID;
    timer.taskEvent = taskEvent;
    timer.nextTimer = NULL;
    timer.periodic = true;
    OSAL_TimerAdd(&timer);
}

/**
 * @fn OSAL_Timer_ProcessEvents
 * @brief 处理OSAL定时器事件
 * @param taskID-设置事件的任务
 * @param taskEvent-设置的事件
 * @return none
 */
uint8_t OSAL_Timer_ProcessEvents(uint8_t taskID, uint16_t event)
{
    uint16_t taskEvent = event;
    if (taskEvent & OSAL_TIMERMGR_UPDATE)
    {

        return taskEvent ^ OSAL_TIMERMGR_UPDATE;
    }
    else
    {
        return taskEvent;
    }
}

/**
 * @fn OSAL_timerBaseInit
 * @brief 设置OSAL定时器的硬件时基
 * @param taskMS-定时器时基，单位ms
 * @return none
 */
void OSAL_timerBaseInit(uint32_t tickMS)
{

    TIM3_Int_Init(4999, 7199); //10Khz的计数频率，计数到5000为500ms
}

/**
 * @fn TIM3_IRQHandler
 * @brief TIM3中断初始化
 * @param arr-自动重装值
 * @param psc-时钟预分频数
 * @return none
 */
void TIM3_Int_Init(u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

    //定时器TIM3初始化
    TIM_TimeBaseStructure.TIM_Period = arr;                     //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler = psc;                  //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);             //根据指定的参数初始化TIMx的时间基数单位

    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能指定的TIM3中断,允许更新中断

    //中断优先级NVIC设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;           //TIM3中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //从优先级3级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);                           //初始化NVIC寄存器

    TIM_Cmd(TIM3, ENABLE); //使能TIMx
}

/**
 * @fn TIM3_IRQHandler
 * @brief TIM3中断
 * @param none
 * @return none
 */
void TIM3_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
    {
        OSAL_afterTimeMS += 10;
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    }
}
